﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LDAPaper
{
    public class Algorithm
    {
        GestureDB trainingDatabase;
        Dictionary<GestureType, double[,]> weights;

        public void Train(GestureDB trainDB)
        {
            this.trainingDatabase = trainDB;
            weights = Common.GetWeights(Parameters.WeightPath);
        }

        public RecognizeResult Recognize(Gesture g)
        {
            RecognizeResult rVal = new RecognizeResult();

            double between = 0;
            double within = 0;

            int betweenCount = 0;
            int withinCount = 0;

            GestureType minCostType = GestureType.UnknownGestureType;

            double minCost = Double.PositiveInfinity;

            for (int i = 0; i < trainingDatabase.TotalClassCount; i++)
            {
                for (int j = 0; j < trainingDatabase[i].Count; j++)
                {
                    if (trainingDatabase[i][j].inputFileName == g.inputFileName)
                        continue;

                    double cost = 0;

                    switch (Parameters.DTWType)
                    {
                        case DTWTypes.ConventionalDTW:

                            switch (Parameters.CoordinateType)
	                        {
                                case CoordinateTypes.OriginalCoordinates:
                                    cost = Common.ConventionalDTW(g.VN, trainingDatabase[i][j].V);
                                    break;
                                case CoordinateTypes.CoordinateDifferences:
                                    cost = Common.ConventionalDTW(g.VDiffsN, trainingDatabase[i][j].VDiffs);
                                    break;
	                        }
                            
                            break;
                        case DTWTypes.OurDTW:

                            switch (Parameters.CoordinateType)
                            {
                                case CoordinateTypes.OriginalCoordinates:
                                    cost = Common.OurDTW(g.VN, trainingDatabase[i][j].V, weights[trainingDatabase[i][0].gestureType]);
                                    break;
                                case CoordinateTypes.CoordinateDifferences:
                                    cost = Common.OurDTW(g.VDiffsN, trainingDatabase[i][j].VDiffs, weights[trainingDatabase[i][0].gestureType]);
                                    break;
                            }
                            
                            break;
                    }

                    if (cost < minCost)
                    {
                        minCost = cost;
                        minCostType = trainingDatabase[i][0].gestureType;
                    }

                    if (g.gestureType == trainingDatabase[i][j].gestureType)
                    {
                        within += cost;
                        withinCount++;
                    }
                    else
                    {
                        between += cost;
                        betweenCount++;
                    }
                }
            }

            between = between / betweenCount;
            within = within / withinCount;

            double ratio = between / within;

            rVal.Ratio = ratio;
            rVal.GestureType = minCostType;

            return rVal;
        }
    }
}
